<?php
/**
 * 返利
 */

namespace Apps\Weixin\Controllers;


use Apps\Acp\Models\AwardLog;
use Apps\Acp\Models\Order;
use Apps\Acp\Models\User;
use Apps\Acp\Services\CampaignService;
use Apps\Acp\Services\UserService;
use Apps\Common\Controller\WeixinBaseController;
use Apps\Common\Model\BaseModel;
use Apps\Weixin\Models\WeixinUnipayLog;
use Apps\Weixin\Services\WxConfigService;
use Deyi\Functions\UtilFunction;
use Vendor\WeixinPay\WeixinPay;

class FanliController extends WeixinBaseController
{
    protected static $shareToken = null;
    protected static $campInfo = null;
    private $from_uid = 0;

    public function initialize()
    {
        $fromToken = $this->getParamValue('st', '', 'string');

        if ($fromToken) {
            $this->from_uid = UtilFunction::urlsafe_b64decode($fromToken);
        } else {
            $this->from_uid = $this->uid;
        }

        static::$campInfo = CampaignService::getInstance()->getOneByFieldCache('id', 1, true);
        if (!static::$campInfo) {
            static::errorThrow('不存在该活动哦！', ExceptionConstant::INTERNAL_ERROR);
        }

        parent::initialize();

        $this->setWeixinJsContextData();

        $this->view->enable();

        $this->view->setVars([
            'campinfo' => static::$campInfo,
            'token' => UtilFunction::urlsafe_b64encode($this->uid),
            'st' => $fromToken,
            'host' => static::$_config->project->apibaseurl
        ]);
    }

    public function indexAction()
    {
        if ($this->uid != $this->from_uid) {
            UserService::getInstance()->checkViews($this->from_uid);
        }
    }

    public function userAction()
    {
        $user = UserService::getInstance()->getOneByFieldCache('id', $this->uid, true);

        $this->view->setVars([
            'user' => $user
        ]);
    }

    public function payAction()
    {

    }

    public function prepayAction()
    {
        $this->mutexlock($this->uid);

        $num = $this->getParamValue('num', null, 'int');
        $phone = $this->getParamValue('phone', null, 'string');

        $outTradeNo = 'UNI' . date('Ymd') . time() . rand(1000, 9999);
        $nonceStr = md5(UtilFunction::getRandomString());
        $nowTime = time();

        $pay_desc = mb_substr(static::$campInfo->title, 0, 25, 'utf-8');
        $total = static::$campInfo->price * $num * 100;

        $prePayId = WeixinPay::getPrePayId(
            static::$_config->weixinpay->unipayappid,
            static::$_config->weixinpay->unipaymchid,
            static::$_config->weixinpay->unipaypaykey,
            $nonceStr,
            $pay_desc,
            '',
            $outTradeNo,
            $total,
            static::$_config->weixinpay->unipaynotifyurl,
            'CNY',
            '',
            'JSAPI',
            static::$wxUserInfo->openid
        );

        $values = [
            'appId' => static::$_config->weixinpay->unipayappid,
            'timeStamp' => strval($nowTime),
            'nonceStr' => $nonceStr,
            'package' => 'prepay_id=' . $prePayId,
            'signType' => 'MD5'
        ];
        $values['paySign'] = WeixinPay::createAppPayPreSign($values, static::$_config->weixinpay->unipaypaykey);

        if ($values) {
            WeixinUnipayLog::getInstance()->insertByFields([
                'out_trade_no' => $outTradeNo,
                'business_id' => '001',
                'business_tradeno' => $outTradeNo,
                'openid' => static::$wxUserInfo->openid,
                'unionid' => static::$wxUserInfo->unionid,
                'pay_desc' => $pay_desc,
                'total_fee' => $total,
                'notify_url' => '',
                'extdata' => json_encode(['num' => $num, 'uid' => $this->uid, 'from_uid' => $this->from_uid, 'phone' => $phone, 'nickname' => static::$wxUserInfo->nickname, 'avatar' => static::$wxUserInfo->headimgurl], JSON_UNESCAPED_UNICODE),
                'appid' => static::$_config->weixinpay->unipayappid,
                'mch_id' => static::$_config->weixinpay->unipaymchid,
                'create_time' => time()
            ]);
        }

        parent::renderSuccessJson([
            'jsPayStr' => $values
        ]);
    }

    public function wxNotifyAction()
    {
        $data = $this->request->getRawBody();
        if (!$data) {
            static::errorThrow('签名验证失败');
        }
        BaseModel::setForceMasterRead(true);
        static::$_logger->info('fanli wxpay notify');
        $wxCall = WeixinPay::getCallbackData($data, static::$_config->weixinpay->unipaypaykey);

        if ($wxCall) {
            $transactionId = $wxCall['transaction_id']; //财付通订单号
            $outTradeNo = $wxCall['out_trade_no']; //商户唯一订单号
            $totalFee = $wxCall['total_fee']; //商品金额,以分为单位
            $mchId = $wxCall['mch_id']; //财付通商户号
            $tradeType = $wxCall['trade_type']; //交易类型
            $feeType = $wxCall['fee_type']; //货币种类
            $bankType = $wxCall['bank_type'];
            try {
                $payDone = false;
                BaseModel::beginTransaction();

                $where = [
                    'out_trade_no' => $outTradeNo,
                    'mch_id' => $mchId,
                    'pay_status' => 0,
                    'total_fee' => $totalFee
                ];
                if (($tradeInfo = WeixinUnipayLog::getInstance()->getOneByFields($where, true)) &&
                    WeixinUnipayLog::getInstance()->updateByFields([
                        'pay_status' => 1,
                        'trade_type' => $tradeType,
                        'bank_type' => $bankType,
                        'fee_type' => $feeType,
                        'transaction_id' => $transactionId,
                        'pay_time' => time(),
                        'notify_status' => 1,
                        'notify_time' => time()
                    ], $where)) {
                    static::$_logger->info('apply done');
                    $payDone = true;
                }

                if (BaseModel::commitTransaction()) {
                    if ($payDone) {
                        $extData = json_decode($tradeInfo->extdata, true);
                        $awardUid = $extData['from_uid'];
                        Order::getInstance()->insertByFields([
                            'uid' => $extData['uid'],
                            'openid' => $tradeInfo->openid,
                            'nickname' => $extData['nickname'],
                            'phone' => $extData['phone'],
                            'avatar' => $extData['avatar'],
                            'tradeno' => $outTradeNo,
                            'from_uid' => $awardUid,
                            'num' => $extData['num'],
                            'total_fee' => $totalFee,
                            'createtime' => time(),
                        ]);

                        $tradeAward = WxConfigService::getInstance()->getTrade();
                        if ($extData['uid'] != $awardUid && $tradeAward) {

                            $user = UserService::getInstance()->getOneByFieldCache('id', $awardUid);
                            $trade_num = $extData['num'] + $user->trade_num;

                            $award = 0;
                            foreach ($tradeAward as $value) {
                                if ($value['from'] <= $trade_num && $value['to'] >= $trade_num) {
                                    $award = $value['award'];
                                    break;
                                }
                            }

                            AwardLog::getInstance()->insertByFields(['uid' => $awardUid, 'type' => 2, 'num' => $award, 'dateline' => time()]);

                            User::getInstance()->updateTradeCount('award', $awardUid, $award);

                            UserService::getInstance()->cleanUserCache('id', $awardUid);
                        }

                        UserService::getInstance()->cleanUserCache('id', $extData['uid']);
                        User::getInstance()->updateCount('buy_num', $extData['uid'], $extData['num']);
                    }
                }
            } catch (\Exception $e) {
                static::$_logger->error('支付回调错误信息：' . $e->getMessage());
                WeixinPay::echoCallbackResult(false, $e->getMessage());
            }
        } else {
            static::$_logger->error('支付回调错误信息：签名验证失败');
            WeixinPay::echoCallbackResult(false, '签名验证失败');
        }
    }

}
